const {
  declare
} = require('@babel/helper-plugin-utils');

//声明一个插件

// 一个函数返回一个对象的格式，对象里有 visitor、pre、post、inherits、manipulateOptions 等属性。

/**
 * inherits：指定继承某个插件，和当前插件的 options 合并，通过 Object.assign 的方式
 * visitor：指定 traverse 时调用的函数
 * pre 和 post 分别在遍历前后调用，可以做一些插件调用前后的逻辑，比如可以往 file（表示文件的对象，在插件里面通过 state.file 拿到）中放一些东西，在遍历的过程中取出来。
 * manipulateOptions 用于修改 options，是在插件里面修改配置的方式，比如 syntaxt plugin一般都会修改 parser options：
 */

const mangle = declare((api, options, dirname) => {

  api.assertVersion(7);

  return {

    pre(file) {
      file.set('uid', 0);
    },
    visitor: {
      Scopable: {
        exit(path, state) {
          // console.log('path ---> ', path.scope.bindings)

          // path.scope.bindings 当前作用域内声明的所有变量
          
          let uid = state.file.get('uid');

          console.log('uid ---> ', uid)

          // state 是遍历过程中 AST 节点之间传递数据的方式。插件的 visitor 中，第一个参数是 path，第二个参数就是 state。
          // 插件可以从 state 中拿到 opts，也就是插件的配置项，也可以拿到 file 对象，file 中有一些文件级别的信息，这个也可以从 path.hub.file 中拿。

          // 遍历[key, binding], [key, binding], [key, binding], [key, binding]

          Object.entries(path.scope.bindings).forEach(([key, binding]) => {

          
            if (binding.mangled) return;

            binding.mangled = true;

            const newName = path.scope.generateUid(base54(uid++));

            console.log('key && name ---> ', key, newName)

            binding.path.scope.rename(key, newName)

          });
          state.file.set('uid', uid);
        }
      }
    }
  }
});

const base54 = (function () {
  var DIGITS = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ$_";
  return function (num) {
    var ret = "";
    do {
      ret = DIGITS.charAt(num % 54) + ret;
      num = Math.floor(num / 54);
      console.log('ret -> ', ret)
    } while (num > 0);
    return ret;
  };
})();


module.exports = mangle;